package person.bangbang.im.Androidgin.Framework;

import person.bangbang.im.Androidgin.Fetion.FetionProtocol;
import person.bangbang.im.Androidgin.Framework.Protocol.OnLoginProcess;
import person.bangbang.im.Androidgin.Loopback.LoopbackProtocol;
import person.bangbang.im.Androidgin.Util.Log;


/**
 * a Androidgin account 
 * usually, this is a wrapper of concrete protocol,
 * and explore some utils to APP.
 * 
 * corresponding to pidgin's account.
 * 
 * NOTE when you want a account, go Accounts class.
 * or u can new one, and DO remember to add it to accounts.
 * 
 * @author bangbang.song@gmail.com
 */
public class Account {
	private static final String TAG = "Account";
	
	private Protocol mProtocol;
	
	/* whether a protocol has attached */
	private boolean mHasAttached = false;
	
	private String mProtocolId;

	/**
	 * TODO: dynamic this function.
	 * 
	 * currently, we just hard-coding here, a better 
	 * solution is needed.
	 * 
	 * ::IMPL::
	 */	
	public Account(String protocolId, String userName, String passward, StatusType type){
		mProtocolId = protocolId;
		Protocol p;
		if ("loopback" == protocolId) {
			p = new LoopbackProtocol(userName, passward, type);
			attach(p);
		} else if ("fetion" == protocolId) { // FETION step 3
			p = new FetionProtocol(userName, passward, type);
			attach(p);
		}
		else { // keep this in the bottom.
			throw (new RuntimeException("protocol:" + protocolId + " this protocol have not been attached yes."));
		}
		
		Log.d(TAG, "protocol : " + p.getProtocolID() + " has attached!!");
	}
	
	public Buddy getMyself(){
		return mProtocol.getMyself();
	}
	public String getProtocolID(){
		return mProtocolId;
	}
	public String getUserName() {
		return mProtocol.getUserName();
	}
	public String getPWD() {
		return mProtocol.getPWD();
	}
	public StatusType getLoginType() {
		return mProtocol.getLoginType();
	}
	
	public void attach(Protocol p) {
		mHasAttached = true;
		mProtocol = p;
	}
	/**
	 * signon? register? connect? so confusing.
	 * @return
	 */
	public boolean signon(){
		if (mHasAttached) {
			return mProtocol.signon();
		} else {
			throw new RuntimeException("you MUST attach the protocol before signon");
		}
	}
	/**
	 * signoff? unregister? unconnect? so confusing
	 * @return
	 */
	public boolean signoff(){
		return mProtocol.signoff();
	}
	
//	public abstract List<IBuddy> getBuddies();
	@Deprecated
	public boolean sendIm(Message msg){
		return mProtocol.sendIm(msg);
	}
	
	public void regOnLoginProcessListener(OnLoginProcess l) {
		mProtocol.regOnLoginProcessListener(l);
	}
	public void unRegOnLoginProcessListener(OnLoginProcess l) {
		mProtocol.unRegOnLoginProcessListener(l);
	}
	
	/**
	 * Account UI operations, used to notify the user of 
	 * status changes and when buddies add this account 
	 * to their buddy lists
	 *
	 */
	public interface OnUiOps {
		/**
		 * 	A buddy who is already on this account's buddy 
		 *  list added this account to their buddy list
		 *  
		 * @param acc
		 * @param remoteUser
		 * @param id
		 * @param alias
		 * @param message
		 */
		public void onNotifyAdd(final Account acc, final String remoteUser, final String id, final String alias, final String message);
		/**
		 * 	This account's status changed. 
		 * 
		 * @param acc
		 * @param statusType
		 */
		public void onStatusChanged(Account acc, StatusType statusType);
		/**
		 * 
		 * @param acc
		 * @param remoteUser
		 * @param id
		 * @param alias
		 * @param message
		 */
		public void onRequestAdd(final Account acc, final String remoteUser, final String id, final String alias, final String message);
		/**
		 * 	Prompt for authorization when someone adds this 
		 *  account to their buddy list
		 */
		public void onRequestAuth();
	
		public void onCloseAccountRequest();
	}
	
}
